/*
    This file is part of Raptor.

    Raptor is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Raptor is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Raptor.  If not, see <http://www.gnu.org/licenses/>.

 */

#include "xmlUrlContainer.h"

#include <QDebug>
#include <QDir>
#include <QUrl>
#include <QDomDocument>
#include <QTemporaryFile>
#include <QThreadPool>

xmlUrlContainer::xmlUrlContainer()
{
	verbose = false;

	reinitLoop = false;
	waitForHttp = false;
	waitInsertAt = 0;
        waitingId = -1;

	waitHttp = QList<S_WAITFOR>();
	waitHttp.clear();

	progress = 0;
	response = QByteArray();
	page = "";
	url = "";
	captchaReturn = "";
	hoster = 0;
	step = 1;

	m_error = ERROR_NONE;
	m_state = STATE_FINISHED;

	captchaDir = QDir::currentPath();
	xmlDir = QDir::currentPath();

	regExpResults = QMap<QString, QString>();
	regExpResults.clear();
	regExpListResults = QMap<QString, QStringList>();
	regExpListResults.clear();

	connect(&http, SIGNAL(requestFinished(int, bool)), this, SLOT(slot_http_requestFinished(int, bool)));
        connect(&http, SIGNAL(readyRead(const QHttpResponseHeader &)), this, SLOT(slot_http_readyRead(const QHttpResponseHeader &)));
        connect(&http, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(slot_http_sslErrors(const QList<QSslError> &)));
}

xmlUrlContainer::~xmlUrlContainer()
{

}

//http ->
void xmlUrlContainer::slot_http_readyRead(const QHttpResponseHeader & resp)
{
        Q_UNUSED(resp);
	response.append(http.readAll());
}

void xmlUrlContainer::slot_http_sslErrors(const QList<QSslError> & errors)
{
	Q_UNUSED(errors);
	http.ignoreSslErrors();
}

void xmlUrlContainer::slot_http_requestFinished(int id, bool httpError)
{
	if(waitingId != id) return;

	if(verbose) qDebug() << "slot_http_requestFinished" << http.lastResponse().keys().join("|");

	if(http.lastResponse().hasKey("Set-Cookie"))
	{
		if(verbose) qDebug() << "cookie:" << http.lastResponse().value("Set-Cookie");
	}

	waitingId = -1;

	if(httpError)
	{
		if(verbose) qDebug() << http.errorString();

		m_error = ERROR_HTTP;
		setState(STATE_FINISHED);
		emit finished(QStringList(), true);
	} else
	{
		page = QString(response);
		if(verbose) qDebug() << page;

		if(waitForHttp)
		{
			waitForHttp = false;

			QString tmpStr = "";
			for(int i=0; i<waitHttp.count(); ++i)
				tmpStr += "|" + waitHttp.at(i).node.nodeName();

			if(verbose) qDebug() << tmpStr << waitHttp.count();

			for(int i=0; i<waitHttp.count(); ++i)
			{
				waitInsertAt = 1;
				if(verbose) qDebug() << "do step after wait:" << waitHttp.at(i).node.nodeName();
				doAction(waitHttp.at(i).node, waitHttp.at(i).it);
				waitHttp.removeFirst();
				i--;

				if(waitInsertAt != 1)
				{
					if(verbose) qDebug() << "should wait once again";
					break;
				}
			}

		} else
		{
			QDomNode get_links = domHoster.elementsByTagName("get_links").at(0);
			QDomNode stepX = get_links.childNodes().at(step-1);

			if(stepX.hasChildNodes())
			{
				//alle moeglichen results durchgehen
				QDomNodeList resultList = stepX.namedItem("result").childNodes();

				for(int i=0; i<resultList.count(); i++)
				{
					//wenn result zutrifft, fuehre alle actions aus
					if(switchResult(resultList.at(i)))
					{
						if(verbose) qDebug() << "result -> 1";

						doAction(resultList.at(i));

						//nur ein result kann zutreffen
						break;
					}
				}
			} else
			{
				if(verbose) qDebug() << "step empty";
			}
		}
	}
}
//<- http

//private ->

void xmlUrlContainer::doAction(const QDomNode &parent, const int startI)
{
	if(waitForHttp)
	{
		if(verbose) qDebug() << "waiting for http";
		return;
	}

	if(verbose) qDebug() << "doAction" << parent.nodeName();

	int redoActionAt = 0;

	if(parent.hasChildNodes())
	{
		QDomNodeList actionList = parent.namedItem("action").childNodes();

		if(verbose) qDebug() << "doAction, count:" << actionList.count() << "start:" << startI;

		for(int i=startI; i<actionList.count(); i++)
		{
			switchAction(actionList.at(i));

			if(reinitLoop)
			{
				redoActionAt = i+1;
				break;
			} else if(waitForHttp)
			{
				if(verbose) qDebug() << "new wait:" << waitInsertAt;
				waitHttp.insert(waitInsertAt, S_WAITFOR(parent, i+1));
				waitInsertAt++;
				break;
			}
		}
	}

	if(reinitLoop)
	{/*
		QFile file("mydocument.xml");
		file.open(QIODevice::ReadWrite);
		QTextStream ts(&file);
		domHoster.save(ts, QDomNode::EncodingFromTextStream);
		file.close();*/

		reinitLoop = false;
		doAction(parent, redoActionAt);
	}
}

void xmlUrlContainer::setState(const E_STATE &state)
{
	m_state = state;
	emit stateChanged();
}

bool xmlUrlContainer::loadXmlFile(const QString &xmlFile)
{
	QFile file(xmlDir + "/" + xmlFile);
	domHoster = QDomDocument("hoster");

	if(!file.open(QIODevice::ReadOnly)) return false;

	if(!domHoster.setContent(&file))
	{
		file.close();
		return false;
	}

	if(domHoster.childNodes().at(0).attributes().contains("captcha"))
	{
		if(domHoster.childNodes().at(0).attributes().namedItem("captcha").nodeValue() == "0")
		{
			emit captcha("-1");
		}
	}

	setState(STATE_XML_LOADED);
	return true;
}

void xmlUrlContainer::loadAvailabelHoster(const QString &folder)
{
	validLinksList = QList<S_HOSTER>();

	QDir tmpDir(folder);
	if(tmpDir.exists())
	{
		tmpDir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks);

		QFileInfoList list = tmpDir.entryInfoList();

		for(int i=0; i<list.size(); ++i)
		{
			QFileInfo fileInfo = list.at(i);

			if(fileInfo.fileName().right(3).toLower() == "xml")
			{
				QFile file(tmpDir.dirName() + "/" + fileInfo.fileName());
				QDomDocument domHoster = QDomDocument("hoster");

				if(file.open(QIODevice::ReadOnly))
				{
					if(domHoster.setContent(&file))
					{
                                                bool allowOtherHostnames = false;
						QString tmpHoster = "";
                                                QString tmpRegExp = "^$";
                                                QString tmpRegExp2 = "^$";

                                                if(domHoster.childNodes().at(0).attributes().contains("host"))
                                                {
                                                        tmpHoster = domHoster.childNodes().at(0).attributes().namedItem("host").nodeValue();
                                                }

                                                if(domHoster.childNodes().at(0).attributes().contains("host"))
                                                {
                                                    allowOtherHostnames = domHoster.childNodes().at(0).attributes().namedItem("allowOtherHostnames").nodeValue() == "1" ? true: false;
                                                }

						QDomNodeList tmpNodeList = domHoster.elementsByTagName("url_regexp");
						if(!tmpNodeList.isEmpty())
						{
                                                    if(tmpNodeList.at(0).attributes().contains("host"))
                                                    {
                                                            tmpRegExp = tmpNodeList.at(0).attributes().namedItem("host").nodeValue();
                                                    }

                                                    if(tmpNodeList.at(0).attributes().contains("link"))
                                                    {
                                                            tmpRegExp2 = tmpNodeList.at(0).attributes().namedItem("link").nodeValue();
                                                    }
						}

                                                validLinksList.append(S_HOSTER(tmpHoster, fileInfo.fileName(), QRegExp(tmpRegExp), QRegExp(tmpRegExp2), allowOtherHostnames));
					}
					file.close();
				}
			}
		}
	}
}

void xmlUrlContainer::doStep()
{
	if(verbose) qDebug() << "doStep";

	QDomNode get_links = domHoster.elementsByTagName("get_links").at(0);
	QDomNode stepX = get_links.childNodes().at(step-1);

	doAction(stepX);
}

void xmlUrlContainer::switchAction(const QDomNode &action)
{
	if(verbose) qDebug() << "action" << action.nodeName() << action.attributes().namedItem("type").nodeValue();

	if(!checkAttributes(action, QStringList() << "type")) return;

	switch(parseType(action.attributes().namedItem("type").nodeValue()))
	{
		default:
		case TYPE_NO_FOUND:

			if(verbose) qDebug() << "Error: xml, unknown action: " + action.attributes().namedItem("type").nodeValue();
			break;

		case TYPE_OPEN_URL:
		{
			if(!checkAttributes(action, QStringList() << "method")) break;

			QUrl tmpUrl;
			response = QByteArray();

			//nach url suchen, wenn keine url angegeben, wird file url genutzt, wenn url mit $beginnt, lade variable $url
			QString tmpStr = "";
			if(action.attributes().contains("url"))
			{
				tmpStr = getVar(action.attributes().namedItem("url").nodeValue());
			}

			if(tmpStr == "")
				tmpUrl = QUrl(url);
			else
				tmpUrl = QUrl(tmpStr);


			//pruefen, welche methode gewahelt werden soll
			switch(parseType(action.attributes().namedItem("method").nodeValue()))
			{
				default:

					m_error = ERROR_XML;
					setState(STATE_FINISHED);
					emit finished(QStringList(), true);
					return;
					break;

				case TYPE_METHOD_GET:
				{
					if(verbose) qDebug() << "GET:" << tmpUrl.host() << tmpUrl.path();

					http.setHost(tmpUrl.host());
					waitingId = http.get(tmpUrl.path());
					break;
				}

				case TYPE_FORM_POST:
				{
					QByteArray post = "";

					QDomNamedNodeMap postData = action.namedItem("post_data").attributes();
					for(int i=0; i<postData.count(); i++)
					{
						if(i > 0) post.append("&");
						post.append(postData.item(i).nodeName() + "=" + getVar(postData.item(i).nodeValue()));
					}

					if(verbose) qDebug() << "FORMPOST:" << tmpUrl.host() << tmpUrl.path() << post;

					QHttpRequestHeader header("POST", tmpUrl.path());
					header.setValue("Host", tmpUrl.host());
					header.setValue("Content-Type", "application/x-www-form-urlencoded");

					http.setHost(tmpUrl.host());
					waitingId = http.request(header, post);
					break;
				}

				case TYPE_METHOD_POST:
				{
					QByteArray post = "";

					QDomNamedNodeMap postData = action.namedItem("post_data").attributes();
					for(int i=0; i<postData.count(); i++)
					{
						if(i > 0) post.append("&");
						post.append(postData.item(i).nodeName() + "=" + getVar(postData.item(i).nodeValue()));
					}

					if(verbose) qDebug() << "POST:" << tmpUrl.host() << tmpUrl.path() << post;

					http.setHost(tmpUrl.host());
					waitingId = http.post(tmpUrl.encodedPath(), post);

					break;
				}
			}

			break;
		}

		case TYPE_REGEXP:
		{
			if(!checkAttributes(action, QStringList() << "regexp")) break;

			QRegExp tmpRegExp(action.attributes().namedItem("regexp").nodeValue());

			if(tmpRegExp.indexIn(page) != -1)
			{
				//wenn var vorhanden, alle vars in regExpResults speichern
				if(action.hasChildNodes())
				{
					QDomNamedNodeMap varList = action.namedItem("var").attributes();

					if(varList.count() == tmpRegExp.numCaptures())
					{
						for(int i=0; i<varList.count(); i++)
						{
							addVar(varList.item(i).nodeName(), tmpRegExp.cap(varList.item(i).nodeValue().toInt()));
						}
					} else
					{
						if(verbose) qDebug() << "error: wrong var number";

						m_error = ERROR_XML;
						setState(STATE_FINISHED);
						emit finished(QStringList(), true);
					}
				}
			}

			break;
		}

		case TYPE_MULTI_REGEXP:
		{
			if(!checkAttributes(action, QStringList() << "regexp")) break;

			QRegExp tmpRegExp(action.attributes().namedItem("regexp").nodeValue());

			if(tmpRegExp.indexIn(page) != -1)
			{
				if(action.hasChildNodes())
				{
					QStringList tmpStrList;
					tmpRegExp.setMinimal(true);
					int pos = 0;

					QDomNamedNodeMap varList = action.namedItem("var").attributes();

					QList<QStringList> tmpList;

					while((pos = tmpRegExp.indexIn(page, pos)) != -1)
					{
						QStringList tmpCapStrList;
						for(int i=0; i<varList.count(); i++)
						{
							tmpCapStrList.append(tmpRegExp.cap(varList.item(i).nodeValue().toInt()));
						}

						tmpList.append(tmpCapStrList);

						pos += tmpRegExp.matchedLength();
					}

					for(int i=0; i<varList.count(); i++)
					{
						QStringList tmpVarStrList;
						for(int o=0; o<tmpList.count(); o++)
						{
							tmpVarStrList.append(tmpList.at(o).at(i));
						}

						if(verbose) qDebug() << "regExpListResults:" << varList.item(i).nodeName() << tmpVarStrList.join("|");
						regExpListResults.insert(varList.item(i).nodeName(), tmpVarStrList);
					}
				}
			}

			break;
		}

		case TYPE_STEP:
		{
			if(!checkAttributes(action, QStringList() << "step")) break;

			step = action.attributes().namedItem("step").nodeValue().toInt();
			break;
		}

		case TYPE_DO_STEP:
		{
			if(!checkAttributes(action, QStringList() << "step")) break;

			step = action.attributes().namedItem("step").nodeValue().toInt();

			doStep();

			break;
		}

		case TYPE_GENERATE_LINK:
		{
			if(!checkAttributes(action, QStringList() << "host" << "path" << "save")) break;

			QUrl tmpUrl;
			QString tmpHost = getVar(action.attributes().namedItem("host").nodeValue());

			if(tmpHost == "")
				tmpUrl = QUrl(url);
			else
				tmpUrl = QUrl(tmpHost);

			tmpHost = tmpUrl.host();

			QString tmpPath = getVar(action.attributes().namedItem("path").nodeValue());

			if(tmpPath.left(1) != "/" && tmpPath.right(1) != "/") tmpPath = "/" + tmpPath;

			if(verbose) qDebug() << "link: http://" + tmpHost + tmpPath;
			addVar(action.attributes().namedItem("save").nodeValue(), "http://" + tmpHost + tmpPath);

			break;
		}

		case TYPE_CAPTCHA:
		{
			if(captchaFile) captchaFile->close();

			if(!checkAttributes(action, QStringList() << "captcha")) break;

			emit captcha(getVar(action.attributes().namedItem("captcha").nodeValue()));
			break;
		}

		case TYPE_LOAD_CAPTCHA:
		{
			if(!checkAttributes(action, QStringList() << "captcha" << "save")) break;

			QString tmpUrl = getVar(action.attributes().namedItem("captcha").nodeValue());

                        captchaFile = new QTemporaryFile(captchaDir + QDir::separator() + validLinksList.at(hoster).name + "_XXXXXX.png");
			captchaFile->setAutoRemove(false);

			if(captchaFile->open())
			{
				addVar(action.attributes().namedItem("save").nodeValue(), captchaFile->fileName());

				http.setHost(QUrl(tmpUrl).host());
				waitingId = http.get(QUrl(tmpUrl).path(), captchaFile);
			} else
			{
				if(verbose) qDebug() << "cant open captcha file";
				m_error = ERROR_XML;
				setState(STATE_FINISHED);
				emit finished(QStringList(), true);
				break;
			}
			break;
		}

		case TYPE_FROM_CAPTCHA:
		{
			if(!checkAttributes(action, QStringList() << "save")) break;

			addVar(action.attributes().namedItem("save").nodeValue(), captchaReturn);

			break;
		}

		case TYPE_HEADER:
		{
			if(!checkAttributes(action, QStringList() << "key" << "save")) break;

			if(http.lastResponse().hasKey(action.attributes().namedItem("key").nodeValue()))
			{
				if(verbose) qDebug() << "header:" << http.lastResponse().value(action.attributes().namedItem("key").nodeValue());
				addVar(action.attributes().namedItem("save").nodeValue(), http.lastResponse().value(action.attributes().namedItem("key").nodeValue()));
			} else
			{
				m_error = ERROR_XML;
				setState(STATE_FINISHED);
				emit finished(QStringList(), true);
				return;
			}

			break;
		}

		case TYPE_APPEND:
		{
			if(!checkAttributes(action, QStringList() << "list" << "value")) break;

			QStringList tmpStrList = QStringList();
			if(regExpListResults.contains(action.attributes().namedItem("list").nodeValue()))
			{
				tmpStrList = regExpListResults.value(action.attributes().namedItem("list").nodeValue());
			}

			tmpStrList.append(getVar(action.attributes().namedItem("value").nodeValue()));

			regExpListResults.insert(action.attributes().namedItem("list").nodeValue(), tmpStrList);

			break;
		}

		case TYPE_FOR_I_IN:
		{
			if(!checkAttributes(action, QStringList() << "i" << "in")) break;

			//ersetze for i in schleife durch xml:
			QDomElement tmpElRoot = domHoster.createElement("auto_generated_loop");
			tmpElRoot.setAttribute("type", "sub_action");

			QDomElement tmpElAction = domHoster.createElement("action");

			if(regExpListResults.contains(action.attributes().namedItem("in").nodeValue()))
			{
				if(action.hasChildNodes())
				{
					QDomNodeList actionList = action.namedItem("do").childNodes();

					QStringList list = regExpListResults.value(action.attributes().namedItem("in").nodeValue());

					if(verbose) qDebug() << "list count:" << list.count() << list.join("|");

					double tmpProgress = 0;
					if(checkAttributes(action, QStringList() << "progress"))
					{
						tmpProgress = action.attributes().namedItem("progress").nodeValue().toDouble() / list.count();
					}

					for(int o=0; o<list.count(); ++o)
					{
						QDomElement tmpSetVar = domHoster.createElement("register_loop_it");
						tmpSetVar.setAttribute("type", "register_var");
						tmpSetVar.setAttribute("save", action.attributes().namedItem("i").nodeValue());
						tmpSetVar.setAttribute("var", list.at(o));
						tmpElAction.appendChild(tmpSetVar);

						if(tmpProgress > 0)
						{
							QDomElement tmpAddProgress = domHoster.createElement("addProgress");
							tmpAddProgress.setAttribute("type", "add_progress");
							tmpAddProgress.setAttribute("value", QString("%1").arg(tmpProgress));
							tmpElAction.appendChild(tmpAddProgress);
						}

						for(int i=0; i<actionList.count(); ++i)
						{
							tmpElAction.appendChild(actionList.at(i).cloneNode(true));
						}
					}
				} else
				{
					if(verbose) qDebug() << "loop has no childs";
				}
			} else
			{
				if(verbose) qDebug() << "list for loop not available" << action.attributes().namedItem("in").nodeValue();
			}

			tmpElRoot.appendChild(tmpElAction);
			QDomNode newNode = action.parentNode().insertAfter(tmpElRoot, action);
			reinitLoop = true;

			break;
		}

		case TYPE_WAIT_HTTP:
		{
			waitForHttp = true;
			break;
		}

		case TYPE_REGISTER_VAR:
		{
			if(!checkAttributes(action, QStringList() << "save" << "var")) break;

			addVar(action.attributes().namedItem("save").nodeValue(), getVar(action.attributes().namedItem("var").nodeValue()));

			break;
		}

		case TYPE_SUB_ACTION:
		{
			doAction(action);
			break;
		}

		case TYPE_FINISH:
		{
			if(!checkAttributes(action, QStringList() << "list")) break;

			QStringList tmpStrList = QStringList();
			if(regExpListResults.contains(action.attributes().namedItem("list").nodeValue()))
			{
				tmpStrList = regExpListResults.value(action.attributes().namedItem("list").nodeValue());
			}

			emit progressChanged(100);
			emit finished(tmpStrList, false);
			break;
		}

		case TYPE_ADD_PROGRESS:
		{
			if(!checkAttributes(action, QStringList() << "value")) break;

			progress += action.attributes().namedItem("value").nodeValue().toDouble();
			if(progress > 100) progress = 100;

			emit progressChanged((int)progress);
			break;
		}

		case TYPE_GENERATE_STR:
		{
			if(!checkAttributes(action, QStringList() << "mask" << "save")) break;

			QString tmpStr = action.attributes().namedItem("mask").nodeValue();

			if(action.hasChildNodes())
			{
				QDomNamedNodeMap repList = action.namedItem("replace").attributes();

				for(int i=0; i<repList.count(); ++i)
				{
					tmpStr.replace(repList.item(i).nodeName(), getVar(repList.item(i).nodeValue()));
				}
			}

			addVar(action.attributes().namedItem("save").nodeValue(), tmpStr);

			break;
		}

		case TYPE_FROM_UNICODE:
		{
			if(!checkAttributes(action, QStringList() << "value" << "save")) break;

			addVar(action.attributes().namedItem("save").nodeValue(), fromUnicode(getVar(action.attributes().namedItem("value").nodeValue())));

			break;
		}
	}
}

bool xmlUrlContainer::checkAttributes(const QDomNode &node, const QStringList &attributes)
{
	for(int i=0; i<attributes.count(); ++i)
	{
		if(!node.attributes().contains(attributes.at(i)))
		{
			m_error = ERROR_XML;
			setState(STATE_FINISHED);
			emit finished(QStringList(), true);
			return false;
		}
	}

	return true;
}

bool xmlUrlContainer::switchResult(const QDomNode &result)
{
	if(verbose) qDebug() << "result" << result.nodeName() << result.attributes().namedItem("type").nodeValue();

	if(!result.attributes().contains("type"))
	{
		m_error = ERROR_XML;
		setState(STATE_FINISHED);
		emit finished(QStringList(), true);
		return false;
	}

	switch(parseType(result.attributes().namedItem("type").nodeValue()))
	{
		default:

			m_error = ERROR_XML;
			setState(STATE_FINISHED);
			emit finished(QStringList(), true);
			return false;
			break;

		case TYPE_REGEXP:
		{
			if(!checkAttributes(result, QStringList() << "regexp")) break;

			QRegExp tmpRegExp(result.attributes().namedItem("regexp").nodeValue());

			if(tmpRegExp.indexIn(page) != -1)
			{
				//wenn var vorhanden, alle vars in regExpResults speichern
				if(result.hasChildNodes())
				{
					QDomNamedNodeMap varList = result.namedItem("var").attributes();

					if(varList.count() == tmpRegExp.numCaptures())
					{
						for(int i=0; i<varList.count(); i++)
						{
							addVar(varList.item(i).nodeName(), tmpRegExp.cap(varList.item(i).nodeValue().toInt()));
						}
					} else
					{
						if(verbose) qDebug() << "error: wrong var number";

						m_error = ERROR_XML;
						setState(STATE_FINISHED);
						emit finished(QStringList(), true);
						return false;
					}
				}

				return true;
			} else
			{
				return false;
			}
			break;
		}

		case TYPE_DUMMY:
		{
			//ueberpruefen, ob regexp gesetzt ist
			if(!result.attributes().contains("result"))
			{
				if(verbose) qDebug() << "Warning in xml file, result not given";
				return true;
			} else
			{
				if(result.attributes().namedItem("result").nodeValue().toInt() == 1)
				{
					return true;
				} else
				{
					return false;
				}
			}

			break;
		}
	}

	return false;
}

int xmlUrlContainer::parseType(const QString &type)
{
	if(type == "open_url")
		return TYPE_OPEN_URL;
	else if(type == "get")
		return TYPE_METHOD_GET;
	else if(type == "post")
		return TYPE_METHOD_POST;
	else if(type == "form_post")
		return TYPE_FORM_POST;
	else if(type == "regexp")
		return TYPE_REGEXP;
	else if(type == "multi_regexp")
		return TYPE_MULTI_REGEXP;
	else if(type == "dummy")
		return TYPE_DUMMY;
	else if(type == "step")
		return TYPE_STEP;
	else if(type == "do_step")
		return TYPE_DO_STEP;
	else if(type == "generate_link")
		return TYPE_GENERATE_LINK;
	else if(type == "captcha")
		return TYPE_CAPTCHA;
	else if(type == "load_captcha")
		return TYPE_LOAD_CAPTCHA;
	else if(type == "from_captcha")
		return TYPE_FROM_CAPTCHA;
	else if(type == "for_i_in")
		return TYPE_FOR_I_IN;
	else if(type == "append")
		return TYPE_APPEND;
	else if(type == "return")
		return TYPE_RETURN;
	else if(type == "header")
		return TYPE_HEADER;
	else if(type == "wait_http")
		return TYPE_WAIT_HTTP;
	else if(type == "register_var")
		return TYPE_REGISTER_VAR;
	else if(type == "sub_action")
		return TYPE_SUB_ACTION;
	else if(type == "finish")
		return TYPE_FINISH;
	else if(type == "add_progress")
		return TYPE_ADD_PROGRESS;
	else if(type == "generate_str")
		return TYPE_GENERATE_STR;
	else if(type == "from_unicode")
		return TYPE_FROM_UNICODE;
	else
		return TYPE_NO_FOUND;
}

void xmlUrlContainer::addVar(const QString &key, const QString &value)
{
	if(verbose) qDebug() << "regExpResults:" << regExpResults.count() << key << value;
	regExpResults.insert(key, value);
}

QString xmlUrlContainer::getVar(const QString &var)
{
	QString tmpStr = var;

	if(tmpStr.left(1) == "$")
	{
		if(regExpResults.contains(tmpStr.mid(1)))
		{
			tmpStr = regExpResults.value(tmpStr.mid(1));
		} else
		{
			m_error = ERROR_XML;
			setState(STATE_FINISHED);
			emit finished(QStringList(), true);
			return "";
		}
	}

	return tmpStr;
}

QString xmlUrlContainer::fromUnicode(const QString &str)
{
	QRegExp rx("&#(\\d*);");
	QString tmpStr = "";

	int pos = 0;
	while((pos = rx.indexIn(str, pos)) != -1)
	{
		tmpStr += QChar(rx.cap(1).toInt());

		pos += rx.matchedLength();
	}

	return tmpStr;
}
//<- private

//public ->

QList<QPair<QPair<QRegExp, bool>, QRegExp> > xmlUrlContainer::getRexExpList()
{
    QList<QPair<QPair<QRegExp, bool>, QRegExp> > tmpList;

    for(int i=0; i<validLinksList.count(); ++i)
    {
        tmpList.append(qMakePair(qMakePair(validLinksList.at(i).regExp, validLinksList.at(i).allowOtherHostnames), validLinksList.at(i).regExp2));
    }

    return tmpList;
}

bool xmlUrlContainer::loadXmlForLink(const QString &DownloadLink, const QString &folder)
{
	url = DownloadLink;

	if(folder != "") loadAvailabelHoster(folder);

	for(int i=0; i<validLinksList.count(); ++i)
	{
                if(validLinksList.at(i).regExp2.indexIn(url) != -1)
		{
			if(loadXmlFile(validLinksList.at(i).file))
			{
				hoster = i;
				return true;
			}
		}
	}

	return false;
}

void xmlUrlContainer::setProxy(QNetworkProxy const &proxy)
{
    http.setProxy(proxy);
}

void xmlUrlContainer::setCaptchaDir(const QString &dir)
{
	captchaDir = dir;
}

void xmlUrlContainer::setXmlDir(const QString &dir)
{
	xmlDir = dir;
	loadAvailabelHoster(xmlDir);
}

void xmlUrlContainer::start()
{
	if(verbose) qDebug() << "start";
	step = 1;

	reinitLoop = false;
	waitForHttp = false;
	waitInsertAt = 0;
	waitHttp = QList<S_WAITFOR>();
	waitHttp.clear();

	progress = 0;
	response = QByteArray();
	page = "";
	captchaReturn = "";

	m_error = ERROR_NONE;
	m_state = STATE_FINISHED;

	regExpResults = QMap<QString, QString>();
	regExpResults.clear();
	regExpListResults = QMap<QString, QStringList>();
	regExpListResults.clear();

	doStep();
}

void xmlUrlContainer::submitCaptcha(const QString &str)
{
	captchaReturn = str;
	doStep();
}
//<- public
